package com.youlu.campus.service.linker.impl;

import com.alibaba.fastjson.JSON;
import com.mongodb.client.result.UpdateResult;
import com.youlu.campus.base.exception.BusinessException;
import com.youlu.campus.common.utils.ShotUrlUtil;
import com.youlu.campus.common.utils.TimeUtils;
import com.youlu.campus.entity.ShortUrlConfig;
import com.youlu.campus.entity.VO.req.ShortUrlConfigQueryVO;
import com.youlu.campus.service.linker.ShortUrlConfigService;
import com.youlu.campus.service.linker.ShortUrlConfigStatisticsService;
import com.youlu.campus.service.platform.PlatformConfigService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.regex.Pattern;

@Service
@Slf4j
public class ShortUrlConfigServiceImpl implements ShortUrlConfigService {
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private PlatformConfigService platformConfigService;
    @Autowired
    private ShortUrlConfigStatisticsService shortUrlConfigStatisticsService;

    @Override
    public Page<ShortUrlConfig> list(ShortUrlConfigQueryVO req) {
        log.info(":>>> 开始获取短来呢集:{}", JSON.toJSONString(req));
        if (Objects.isNull(req)) {
            log.error(":>>> 参数错误");
            throw new BusinessException("参数错误");
        }
        Query query = new Query();
        if (StringUtils.isNotBlank(req.getOptLoginName())) {
            query.addCriteria(Criteria.where("optLoginName").is(req.getOptLoginName()));
        }
        if (StringUtils.isNotBlank(req.getType())) {
            query.addCriteria(Criteria.where("type").is(req.getType()));
        }
        if (StringUtils.isNotBlank(req.getPlatform())) {
            query.addCriteria(Criteria.where("platform").is(req.getPlatform()));
        }
        if (StringUtils.isNotBlank(req.getName())) {
            Pattern pattern = Pattern.compile("^.*" + req.getName() + ".*$", Pattern.CASE_INSENSITIVE);
            query.addCriteria(Criteria.where("name").regex(pattern));
        }
        if (StringUtils.isNotBlank(req.getDesc())) {
            Pattern pattern = Pattern.compile("^.*" + req.getDesc() + ".*$", Pattern.CASE_INSENSITIVE);
            query.addCriteria(Criteria.where("desc").regex(pattern));
        }
        if (StringUtils.isNotBlank(req.getShortUrl())) {
            query.addCriteria(Criteria.where("shortUrl").is(req.getShortUrl()));
        }
        if (StringUtils.isNotBlank(req.getKey())) {
            query.addCriteria(Criteria.where("key").is(req.getKey()));
        }
        query.addCriteria(Criteria.where("deleted").ne(true));
        long count = mongoTemplate.count(query, ShortUrlConfig.class);
        PageRequest pageRequest = PageRequest.of(req.getPage() - 1, req.getPageSize());
        Sort sort = Sort.by(Sort.Direction.DESC, "createdTime");
        query.with(sort);
        List<ShortUrlConfig> infos = mongoTemplate.find(query.with(pageRequest), ShortUrlConfig.class);
        for (ShortUrlConfig config : infos) {
            Long counter = shortUrlConfigStatisticsService.getCounter(config.getId());
            config.setCounter(counter);
        }
        return PageableExecutionUtils.getPage(infos, pageRequest, () -> count);
    }

    @Override
    public boolean create(ShortUrlConfig req) {
        log.info(":>>> 开始创建短链接:{}", JSON.toJSONString(req));
        if (Objects.isNull(req) || StringUtils.isBlank(req.getName()) || StringUtils.isBlank(req.getDesc())) {
            log.error(":>>> 创建短链接参数错误");
            throw new BusinessException("创建短链接参数错误");
        }
        if (StringUtils.isBlank(req.getLongUrl()) || req.getLongUrl().contains(" ")) {
            log.error(":>>> 长链接地址包含空格或为空");
            throw new BusinessException("长链接地址包含空格");
        }
        String key = this.generateShortUrl(req.getLongUrl());
        String domain = platformConfigService.getShortConfigDomain();
        req.setId(null);
        req.setCreatedTime(new Date());
        req.setKey(key);
        req.setDomain(domain);
        req.setShortUrl(platformConfigService.getShortConfigDomain() + "/" + key);
        req = mongoTemplate.insert(req);
        log.info(":>>> 生成的短链接配置信息:{}", JSON.toJSONString(req));
        return true;
    }

    @Override
    public boolean update(ShortUrlConfig req) {
        log.info(":>>> 开始修改短链接:{}", JSON.toJSONString(req));
        if (Objects.isNull(req) || StringUtils.isBlank(req.getId())) {
            log.error(":>>> 修改短链接参数错误");
            throw new BusinessException("修改短链接参数错误");
        }
        ShortUrlConfig exist = this.findOne(req.getId());
        if (Objects.isNull(exist)) {
            log.error(":<<< 短链接配置:{} 不存在");
            throw new BusinessException("短链接配置");
        }
        Query query = new Query().addCriteria(Criteria.where("id").is(req.getId()));
        Update update = new Update();
        if (StringUtils.isNotBlank(req.getName())) {
            update.set("name", req.getName());
        }
        if (StringUtils.isNotBlank(req.getDesc())) {
            update.set("desc", req.getDesc());
        }
        if (StringUtils.isNotBlank(req.getType())) {
            update.set("type", req.getType());
        }
        if (StringUtils.isNotBlank(req.getLongUrl()) && !req.getLongUrl().equals(exist.getLongUrl())) {
            update.set("longUrl", req.getLongUrl());
            String opt = TimeUtils.formatDate(new Date(), "yyyy-MM-dd HH:MM:SS") + "," + req.getOptLoginName() + ",将链接修改为:" + req.getLongUrl();
            exist.getOptLogs().add(opt);
            update.set("optLogs", exist.getOptLogs());
        }
        update.set("updatedTime", new Date());
        UpdateResult updateResult = mongoTemplate.updateFirst(query, update, ShortUrlConfig.class);
        return updateResult.getModifiedCount() > 0 ? true : false;
    }

    @Override
    public ShortUrlConfig findOne(String id) {
        Query query = new Query().addCriteria(Criteria.where("id").is(id));
        ShortUrlConfig config = mongoTemplate.findOne(query, ShortUrlConfig.class);
        return config;
    }

    @Override
    public boolean delete(String id) {
        Query query = new Query().addCriteria(Criteria.where("id").is(id));
        Update update = new Update();
        update.set("updatedTime", new Date());
        update.set("deleted", true);
        UpdateResult updateResult = mongoTemplate.updateFirst(query, update, ShortUrlConfig.class);
        return updateResult.getModifiedCount() > 0 ? true : false;
    }

    @Override
    public String generateShortUrl(String longUrl) {
        log.info(":>>> 开始生成短链接:{}", longUrl);
        String shortUrl = ShotUrlUtil.shortUrl(longUrl);
        return shortUrl;
    }

    @Override
    public ShortUrlConfig findByKey(String key) {
        Query query = new Query().addCriteria(Criteria.where("key").is(key));
        ShortUrlConfig config = mongoTemplate.findOne(query, ShortUrlConfig.class);
        return config;
    }

    @Override
    public void updateAllDomain() {
        log.error("updateAllDomain 批量修改连接域名");
        Query query = new Query();
        query.addCriteria(Criteria.where("type").is("A"));
        List<ShortUrlConfig> configList = mongoTemplate.find(query, ShortUrlConfig.class);
        if (CollectionUtils.isEmpty(configList)) {
            return;
        }
        String domain = platformConfigService.getShortConfigDomain();
        String bizFrontDomain = platformConfigService.getBizFrontDomain();
        Date date = new Date();
        LocalDateTime now = LocalDateTime.now();
        for (ShortUrlConfig shortUrlConfig : configList) {
            //如果短链接域名地址 与 当前域名一致则跳过
            if (shortUrlConfig.getShortUrl().startsWith(domain)) {
                continue;
            }
            //操作日志
            List<String> optLogs = shortUrlConfig.getOptLogs();
            if (CollectionUtils.isEmpty(optLogs)) {
                optLogs = new ArrayList<>();
            }
            optLogs.add(now + "短连接批量更新域名 老域名:" + shortUrlConfig.getDomain() + " 新域名:" + domain);

            //暂不更新长连接 长连接存在定制的问题
            //String longUrl = replaceDomain(shortUrlConfig.getLongUrl(), bizFrontDomain);
            //optLogs.add(now + "长连接批量更新域名 新链接:" + longUrl);
            //shortUrlConfig.setLongUrl(longUrl);

            //更新域名
            shortUrlConfig.setDomain(domain);
            shortUrlConfig.setShortUrl(domain + "/" + shortUrlConfig.getKey());
            shortUrlConfig.setUpdatedTime(date);
            mongoTemplate.save(shortUrlConfig);
            log.info("updateAllDomain 批量修改连接域名 shortUrlConfig:{}", JSON.toJSONString(shortUrlConfig));
        }
    }

    public static String replaceDomain(String originalUrl, String newDomain) {
        String new_originalUrl = originalUrl;
        if (originalUrl.startsWith("https://")) {
            new_originalUrl = originalUrl.replace("https://", "");
        }
        if (new_originalUrl.contains("/")) {
            new_originalUrl = originalUrl.substring(originalUrl.indexOf("/"), originalUrl.length() - 1);
            return newDomain + "" + new_originalUrl;
        } else {
            return originalUrl;
        }
    }
}
